/*
 * Eugen Stoian <stoian.e@gmail.com> 2010
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Project.h"
#include "Expression3D.h"
#include "Curve3D.h"
#include "Surface3D.h"

Project::Project(const QString& name, QObject *parent)
    :QObject(parent),_changed(false){
    setObjectName(name);
}

void Project::addExpression(Expression3D* expr){
    expr->setParent(this);
    _expressions.append(expr);
    _changed = true;
    emit changed();
}

void Project::deleteExpression(const QString& name){
    QList<Expression3D*>::iterator e;
    for(e = _expressions.begin();e!=_expressions.end();++e)
        if((*e)->objectName()==name){
            delete (*e);
            _expressions.erase(e);
            _changed =true;
        }
    if(_changed)
        emit changed();
}

void Project::addPlot(ParametricObject3D* pp){
    pp->setParent(this);
    _plots.append(pp);
    _changed =true;
    emit changed();
}

void Project::addCurve(Curve3D* curve){
    curve->setParent(this);
    _plots.append(curve);
    _changed =true;
    emit changed();
}

void Project::addSurface(Surface3D* surf){
    surf->setParent(this);
    _plots.append(surf);
    _changed =true;
    emit changed();
}

void Project::deletePlot(const QString& name){
    QList<ParametricObject3D*>::iterator p;
    for(p = _plots.begin();p!=_plots.end();++p)
        if(((*p)->objectName()==name)){
            delete (*p);
            _plots.erase(p);
            _changed =true;
        }
    if(_changed)
        emit changed();
}

Expression3D* Project::findExpression(const QString& name){
    QList<Expression3D*>::iterator e;
    for(e = _expressions.begin();e!=_expressions.end();++e)
        if((*e)->objectName()==name){
            return (*e);
        }
    return 0;
}

ParametricObject3D* Project::findObject(const QString& name){
    QList<ParametricObject3D*>::iterator pp;
    for(pp = _plots.begin();pp!=_plots.end();++pp)
        if((*pp)->objectName()==name){
            return (*pp);
        }
    return 0;
}

void Project::cleanUp(){

    QList<ParametricObject3D*>::iterator p;
    for(p = _plots.begin();p!=_plots.end();++p){
        delete (*p);
    }
    _plots.clear();
    QList<Expression3D*>::iterator e;
    for(e = _expressions.begin();e!=_expressions.end();++e){
            delete (*e);
    }
    _expressions.clear();
}

QDataStream& operator<<(QDataStream& stream, const Project& p){
    int count = p._expressions.count();
    stream << count;
    for(int i = 0; i < count;++i){
        stream << *(p._expressions.at(i));
    }
    count = p._plots.count();
    stream << count;
    for(int i = 0; i <count;++i){
        stream << *(p._plots.at(i));
    }
    return stream;
}

QDataStream& operator>>(QDataStream& stream, Project& p){
    int count;
    stream >> count;
    for(int i = 0; i < count; ++i){
        Expression3D* expr = new Expression3D(&p);
        stream >> *expr;
        p._expressions.append(expr);
    }
    stream >> count;
    for(int i = 0; i < count; ++i){
        int type;
        stream >> type;
        ParametricObject3D* pp;
        if(type==Object::Curve)
            pp = new Curve3D(&p);
        else
            pp = new Surface3D(&p);
        stream >> *pp;
        p.addPlot(pp);
    }
    return stream;
}
